package aceim.protocol.snuk182.icq.inner.dataprocessing;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import aceim.protocol.snuk182.icq.inner.ICQConstants;
import aceim.protocol.snuk182.icq.inner.ICQException;
import aceim.protocol.snuk182.icq.inner.ICQServiceInternal;
import aceim.protocol.snuk182.icq.inner.dataentity.Flap;
import aceim.protocol.snuk182.icq.inner.dataentity.ICQBuddy;
import aceim.protocol.snuk182.icq.inner.dataentity.ICQBuddyGroup;
import aceim.protocol.snuk182.icq.inner.dataentity.ICQBuddyList;
import aceim.protocol.snuk182.icq.inner.dataentity.ICQIconData;
import aceim.protocol.snuk182.icq.inner.dataentity.ICQOnlineInfo;
import aceim.protocol.snuk182.icq.inner.dataentity.Snac;
import aceim.protocol.snuk182.icq.inner.dataentity.TLV;
import aceim.protocol.snuk182.icq.utils.ProtocolUtils;
public abstract class AbstractFlapProcessor implements IFlapProcessor {
protected ICQServiceInternal service;
List<ICQBuddy> buddies = null;
List<ICQBuddyGroup> groups = null;
Map<String, Short> permitList = new HashMap<String, Short>();
Map<String, Short> denyList = new HashMap<String, Short>();
List<ICQBuddy> ignoreList = new ArrayList<ICQBuddy>();
List<ICQBuddy> notAuthList = new ArrayList<ICQBuddy>();
@Override
public void init(ICQServiceInternal service) throws ICQException {
this.service = service;
}
@Override
public void process(Flap flap) throws ICQException{
internalFlapMap(flap);
}
protected abstract void internalFlapMap(Flap flap) throws ICQException;
protected void fillOnlineInfoParams(TLV[] tlvs, ICQOnlineInfo info) throws ICQException{
for (int i=0; i<tlvs.length; i++){
TLV tlv = tlvs[i];
switch(tlv.type){
case 0xca:
info.visibility = tlv.value[0];
break;
case 0xcb:
//user class visibility - unused for now;
break;
case 0xcc:
try {
info.handheldNotification = tlv.value[7]!=2;
info.idleTimeNotification = tlv.value[5]==4;
info.typingNotification = tlv.value[5]==4;
} catch (Exception e) {
service.log(e);
}
break;
}
}
}
protected void parseBuddyList(byte[] plainData, boolean hasMore) throws ICQException{
service.log(" parse buddy list "+ProtocolUtils.getSpacedHexString(plainData));
ICQBuddyList buddyList = service.getBuddyList();
buddyList.ssiVersion = plainData[0];
int itemCount = ProtocolUtils.unsignedShort2Int(ProtocolUtils.bytes2ShortBE(plainData, 1));
service.log(" item count "+itemCount);
buddyList.itemNumber = itemCount;
if (buddies == null || groups == null){
buddies = new ArrayList<ICQBuddy>();
groups = new ArrayList<ICQBuddyGroup>();
}
int pos = 3;
int itemPos = 0;
List<Short> existingIDs = new ArrayList<Short>(itemCount);
while (itemPos<itemCount){
int nameLength = ProtocolUtils.unsignedShort2Int(ProtocolUtils.bytes2ShortBE(plainData, pos));
pos+=2;
String name = null;
try {
name = new String(plainData, pos, nameLength, "UTF-8");
} catch (UnsupportedEncodingException e) {
name = new String(plainData, pos, nameLength);
}
pos+=nameLength;
short groupId = ProtocolUtils.bytes2ShortBE(plainData, pos);
pos+=2;
short itemId = ProtocolUtils.bytes2ShortBE(plainData, pos);
pos+=2;
short flagType = ProtocolUtils.bytes2ShortBE(plainData, pos);
pos+=2;
int tlvLength = ProtocolUtils.unsignedShort2Int(ProtocolUtils.bytes2ShortBE(plainData, pos));
pos+=2;
existingIDs.add(itemId);
TLV[] tlvs = null;
if (tlvLength>0){
byte[] buffer = new byte[tlvLength];
System.arraycopy(plainData, pos, buffer, 0, tlvLength);
try {
tlvs = service.getDataParser().parseTLV(buffer);
} catch (ICQException e) {
service.log(e);
}
}
service.log(" item name "+name +" flag "+flagType);
pos+=tlvLength;
switch(flagType){
case 0x0:
ICQBuddy buddy = new ICQBuddy();
buddy.uin = name;
buddy.groupId = groupId;
buddy.itemId = itemId;
buddy.flagType = flagType;
buddy.setAdditional(tlvs, notAuthList);
buddies.add(buddy);
break;
case 0x1:
if (groupId!=0x0){
ICQBuddyGroup group = new ICQBuddyGroup();
group.name = name;
group.groupId = groupId;
group.setAdditional(tlvs);
groups.add(group);
}
break;
case 0x2:
permitList.put(name, itemId);
break;
case 0x3:
denyList.put(name, itemId);
break;
case 0x4:
service.getOnlineInfo().itemId = itemId;
fillOnlineInfoParams(tlvs, service.getOnlineInfo());
break;
case 0x5:
//presence info
break;
case 0x9:
//wtf
break;
case 0xe:
ICQBuddy ignored = new ICQBuddy();
ignored.uin = name;
ignored.groupId = groupId;
ignored.itemId = itemId;
ignored.flagType = flagType;
ignored.setAdditional(tlvs, notAuthList);
ignored.visibility = ICQConstants.VIS_IGNORED;
ignoreList.add(ignored);
break;
case 0xf:
//service.getBuddyList().setLastUpdateTime(Utils.bytes2Date());
break;
case 0x10:
//non-icq contact
break;
case 0x13:
//roster import time
break;
case 0x14:
service.log("icon info ");
ICQIconData iconData = new ICQIconData();
iconData.ssiItemId = itemId;
service.getOnlineInfo().iconData = iconData;
break;
}
itemPos++;
}
buddyList.lastUpdateTime = new Date(ProtocolUtils.unsignedInt2Long(ProtocolUtils.bytes2IntBE(plainData, pos))*1000);
/*Map<String, String> ssiMap = new HashMap<String, String>();
ssiMap.put(ICQConstants.SAVEDPREFERENCES_SSI_ITEM_COUNT, itemCount+"");
ssiMap.put(ICQConstants.SAVEDPREFERENCES_SSI_UPDATE_DATE, buddyList.lastUpdateTime.getTime()+"");
service.getServiceResponse().respond(ICQServiceResponse.RES_SAVETOSTORAGE, ICQConstants.SAVEDPREFERENCES_NAME, ssiMap);*/
if (!hasMore){
Set<String> permits = permitList.keySet();
for (String uin:permits){
for (ICQBuddy buddy:buddies){
if (uin.equalsIgnoreCase(buddy.uin)){
buddy.visibility = ICQConstants.VIS_PERMITTED;
service.log("permitted "+uin);
break;
}
}
}
Set<String> denys = denyList.keySet();
for (String uin:denys){
for (ICQBuddy buddy:buddies){
if (uin.equalsIgnoreCase(buddy.uin)){
buddy.visibility = ICQConstants.VIS_DENIED;
service.log("denied "+uin);
break;
}
}
}
service.setBuddyList(buddies, groups, permitList, denyList, notAuthList, existingIDs);
buddies = null;
groups = null;
}
}
protected abstract void internalTLVMap(TLV tlv)throws ICQException;
protected abstract void internalSnacMap(Snac snac)throws ICQException;
}